﻿using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System;
using System.Linq;

namespace Monti.Docking
{
   /// <summary>
   /// A dock group used for binding to the dock manager.
   /// </summary>
   public class DockGroup
   {
      /// <summary>
      /// Initializes a new dock group.
      /// </summary>
      public DockGroup ()
      {
         this.Parent = null;
         this.Items = new ObservableCollection <object> ();
         this.Children = new ObservableCollection <DockGroup> ();
         this.Children.CollectionChanged += ChildrenCollectionChanged;
         this.Items.CollectionChanged += ItemsCollectionChanged;
         this.DockArea = DockArea.Document;
      }

      /// <summary>
      /// Gets or Sets the dock area;
      /// </summary>
      public DockArea DockArea { get; set; }

      /// <summary>
      /// Gets the parent dock group, if any.
      /// </summary>
      public DockGroup Parent { get; private set; }

      /// <summary>
      /// Gets or Set the dock site the group is attached to.
      /// </summary>
      internal DockSite DockSite { get; set; }

      /// <summary>
      /// Gets the items in the dock group.
      /// </summary>
      public ObservableCollection<object> Items { get; internal set; }

      /// <summary>
      /// Gets the list of children.
      /// </summary>
      public ObservableCollection<DockGroup> Children { get; private set; }

      /// <summary>
      /// Occurs when the items collection changes.
      /// </summary>
      /// <param name="sender">Items colleciton.</param>
      /// <param name="e">NotifyCollectionChangedEventArgs</param>
      private void ItemsCollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
      {
         if (e.Action == NotifyCollectionChangedAction.Add)
         {
            if (e.NewItems != null)
            {
               foreach (var dockItem in e.NewItems.OfType <IDockGroupAware> ())
                  dockItem.DockGroup = this;
            }
         }
      }

      /// <summary>
      /// Occurs when the children change, used to validate the dock position.
      /// </summary>
      /// <param name="sender">Children collection.</param>
      /// <param name="e">NotifyCollectionChangedEventArgs</param>
      private void ChildrenCollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
      {
         if (e.Action == NotifyCollectionChangedAction.Add)
         {
            foreach (DockGroup item in e.NewItems)
               item.Parent = this;
         }

         if (this.Children.Any (child => child.DockArea == DockArea.Document))
            throw new InvalidOperationException ("Child dock group cannot be docked to the center!");
      }
   }
}
